// @ts-check

import { useState, useEffect } from 'react';
import { debounce } from 'lodash-es';

const SMALL_ONLY = '(max-width:767px)';
const MEDIUM_ONLY = '(max-width:959px) and (min-width:768px)';
const LARGE_ONLY = '(max-width:1289px) and (min-width:960px)';
const MEDIUM_UP = '(min-width:768px)';
const LARGE_UP = '(min-width:960px)';
const XLARGE_UP = '(min-width:1290px)';

/**
 * @typedef ScreenName
 * @type {'small'|'meidum'|'large'|'xlarge'}
 */

/**
 * @type {Object.<ScreenName, Function>}
 */
const availableQuery = {
    small: () => window.matchMedia(SMALL_ONLY),
    medium: () => window.matchMedia(MEDIUM_ONLY),
    large: () => window.matchMedia(LARGE_ONLY),
    xlarge: () => window.matchMedia(XLARGE_UP),
};

/**
 * @returns ScreenName
 */
const getCurrentScreen = () => Object.keys(availableQuery).find(screenName => availableQuery[screenName]().matches);

/**
 * @param {Object.<ScreenName, any>} map
 * @returns {*} the value matched current screen size
 */
export default function useResponsive(map) {
    const [currentScreen, setCurrentScreen] = useState(getCurrentScreen());

    useEffect(() => {
        const recalculate = debounce(() => setCurrentScreen(getCurrentScreen()), 500);
        window.addEventListener('resize', recalculate);
        return () => {
            window.removeEventListener('resize', recalculate);
        };
    }, []);

    /**
     * support auto match large screen
     * props.value: { small: 300, large: 400 }
     * if current screen is medium, then result is 300
     * if current screen is xlarge, then result is 400
     * @return ScreenName
     */
    const getNextLargestScreen = () => {
        const allScreens = Object.keys(availableQuery);
        const currentScreenIndex = allScreens.findIndex(x => x === currentScreen);

        return allScreens
            .filter((x, index) => index <= currentScreenIndex)
            .reverse()
            .find(screen => map[screen] !== undefined);
    };

    const targetValue = map[currentScreen];
    return targetValue || map[getNextLargestScreen()];
}
